#include "vtor_printf.h"

#ifdef __VTOR_PRINTF__

#if 0
int16_t VtorString_Printf(const char *format, ...)
{
	// https://blog.csdn.net/qq_32108893/article/details/78682531
	uint8_t str[128] = {'\0'}; 
	va_list ap;
	va_start(ap, format);
	vsprintf((char *)str, format, ap);
	va_end(ap);
	return VtorString_Print(str);
}
#endif


#if 0
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
	int handle; 
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
	x = x;
}

//重定义fputc函数
int fputc(int ch, FILE *f)
{
	while((USART1->SR&0X40)==0){};//循环发送,直到发送完毕
	USART1->DR = (uint8_t) ch;
	return ch;
}
#endif 


const VtorPrintColor printColor[] = 
{
	VtorPrintResetColor,	"\033[0m",
	VtorPrintRedColor,		"\033[31m",
	VtorPrintOrangeColor,	"\033[38;5;208m",
	VtorPrintYellowColor,	"\033[33m",
	VtorPrintGreenColor,	"\033[32m",
	VtorPrintCyanColor,		"\033[36m",
	VtorPrintBlueColor,		"\033[34m",
	VtorPrintPurpleColor,	"\033[35m",
	0,						NULL,
};

uint32_t VtorPrintf_GetColorIdx(uint32_t ch)
{
	uint32_t colorIdx = 0;
	while(printColor[colorIdx].colorAnsi)
	{
		if((ch & 0xf0) == printColor[colorIdx].colorAnsi)
		{
			break;
		}
		colorIdx++;
	}
	return colorIdx;
}

uint8_t* VtorPrintf_Reprocess(uint32_t ch, uint8_t* str, int32_t* len)
{
	// 如果此通道有设置颜色，才执行重置颜色
	if(ch & 0xf0)
	{
		str = VtorString_AppendString(str, len, printColor[0].colorStr);
	}
	return str;
}

uint8_t* VtorPrintf_Preprocess(uint32_t ch, uint8_t* str, int32_t* len)
{
	if(ch & 0xf0)
	{
		uint32_t colorIdx = VtorPrintf_GetColorIdx(ch);
		str = VtorString_AppendString(str, len, printColor[colorIdx].colorStr);
	}
	return str;
}


uint8_t* VtorString_AlignMemory(uint8_t* base, int8_t typeSize)
{
    // 计算当前地址与 typeSize 的最近整数倍之间的差值
    int alignment = (int)base % typeSize;
    if (alignment != 0) {
        // 如果当前地址不是 typeSize 的整数倍，则增加到下一个整数倍
        // (typeSize - alignment) 计算出需要增加的字节数
        base += typeSize - alignment;
    }
	return base;
}

int32_t VtorSprintf(uint8_t* str, int32_t len, uint8_t* format, ...)
{
	uint32_t ch = 0; // 输出通道，默认printf使用0
	// 根据入参str是否为NULL，决定直接打印还是存储在字符串内
	uint8_t innerTempBuffer[VTOR_SPRINTF_BUFFER_SIZE] = { '\0' };
	if((uint32_t)str < 0xff) // 允许0xff个不同的输出渠道
	{
		ch = (uint32_t)str;
		// 如果走特殊通道，那么调整str指针
		str = innerTempBuffer;
		len = VTOR_SPRINTF_BUFFER_SIZE;
	}

	uint8_t* buf = str;
	uint8_t* fmt = (uint8_t*)format;
	uint8_t* arg = (uint8_t*)((int32_t*)&format + 1);
	uint8_t widthCh = 0; // 宽度指定符

	VtorString_Clear(buf);
	// 预处理，比如配置颜色
	buf = VtorPrintf_Preprocess(ch, buf, &len);
	while (*fmt && len > 0)
	{
		if(*fmt == '%')
		{
			fmt++; // 判断之后，直接跳过格式指示符的起始符号(%)
			widthCh = 0;
			while('0' <= *fmt && *fmt <= '9')
			{
				widthCh *= 10;
				widthCh += *fmt - '0';
				fmt += 1; // 慢慢跳过宽度指定符
			}
			switch (*fmt)
			{
			case 'x':
			case 'd':
				// 栈内元素需要对齐，int，string向上增长，对4对齐
				arg = VtorString_AlignMemory(arg, 4);
				if(*fmt == 'd')
				{
					buf = VtorString_AppendInt(buf, &len, *(int*)arg);
				}
				else
				{
					buf = VtorString_AppendHex(buf, &len, *(int*)arg);
				}
				arg += 4;
			break;
			case 'f':
				arg = VtorString_AlignMemory(arg, 8);
				buf = VtorString_AppendFloat(buf, &len, *(double*)arg);
				arg += 8;
			break;
			case 'c':
				arg = VtorString_AlignMemory(arg, 4);
				buf = VtorString_AppendChar(buf, &len, (uint8_t)*(int*)arg);
				arg += 4;
			break;
			case 's':
				arg = VtorString_AlignMemory(arg, 4);
				buf = VtorString_AppendString(buf, &len, (uint8_t*)((*(int*)arg)));
				arg += 4;
			break;
			case 'm':
				arg = VtorString_AlignMemory(arg, 4);
				buf = VtorString_AppendMemory(buf, &len,
					(uint8_t*)((*(int*)arg)), *((int*)arg + 1), widthCh);
				arg += 4;
				arg += 4;
			break;
			default:
				
			break;
			}
			fmt += 1; // 只 跳过 格式说明符
		}
		else
		{
			*buf = *fmt;
			buf++;
			len--;
			fmt++;
		}
	}
	buf = VtorPrintf_Reprocess(ch, buf, &len);
	// 保持递增空栈规则，始终指向下一个，后面计算长度需要减1
	*buf++ = '\0';

	// 如果使用了前0xff个特殊通道，那么通过通道打印
	if(str == innerTempBuffer)
	{
		return VtorString_ChanPrintBuffer(ch , str, buf - str - 1);
	}
	// 反之，如果使用了内存，那么直接放在内存即可，不需要其他任何操作
	return buf - str - 1;
}


// VtorScanf("12345 56789", "%d%d", &a, &b);
// VtorScanf("12345 123.456", "%d%d", &a, &f1);
int32_t VtorScanf(uint8_t* str, uint8_t* format, ...)
{
	if((uint32_t)str < 0xff) // 允许0xff个不同的输出渠道
	{
		return 0;
	}

	uint8_t* buf = str;
	uint8_t* fmt = (uint8_t*)format;
	uint8_t* arg = (uint8_t*)((int32_t*)&format + 1);
	
	while (*fmt)
	{
		if(*fmt == '%')
		{
			switch (*(fmt + 1))
			{
			case 'x':
			case 'd':
				// 栈内元素需要对齐，int，string向上增长，对4对齐
				arg = VtorString_AlignMemory(arg, 4);
				buf = VtorString_FindInt(buf, (int32_t*)*((int32_t*)arg));
				arg += 4;
			break;
			case 'f':
				arg = VtorString_AlignMemory(arg, 4);
				buf = VtorString_FindFloat(buf, (float*)*((int32_t*)arg));
				arg += 4;
			break;
			case 's': // 字符串，暂不支持
			break;
			case 'm': // 内存，暂不支持
			break;
			default:
				
			break;
			}
			fmt += 2; // 跳过 百分号  和 格式控制符号
		}
		else
		{
			buf++;
			fmt++;
		}
	}
	
	return buf - str;
}


#endif // __VTOR_PRINTF__



